﻿using System;
using System.Windows.Input;
using DG.Common.Annotations;

namespace DG.Common.Patterns.Commands
{
    public class FunctionalCommand : CommandBase, ICommand
    {
        [NotNull] private readonly Action<object> _execute;
        [NotNull] private readonly Func<object, bool> _canExecute;

        #region Constructors
        public FunctionalCommand([NotNull] Action execute)
            : this(execute, obj => true)
        {}
        public FunctionalCommand([NotNull] Action<object> execute)
            : this(execute, obj => true)
        {}
        public FunctionalCommand([NotNull] Action<object> execute, [NotNull] Func<bool> canExecute)
            : this(execute, obj => canExecute())
        {}
        public FunctionalCommand([NotNull] Action execute, [NotNull] Func<bool> canExecute)
            : this(obj => execute(), obj => canExecute())
        {}
        public FunctionalCommand([NotNull] Action execute, [NotNull] Func<object, bool> canExecute)
            : this(obj => execute(), canExecute)
        {}
        public FunctionalCommand([NotNull] Action<object> execute, [NotNull] Func<object, bool> canExecute)
        {
            if (execute == null) throw new ArgumentNullException("execute");
            if (canExecute == null) throw new ArgumentNullException("canExecute");

            _execute = execute;
            _canExecute = canExecute;
        }

        #endregion

        public void Execute(object parameter)
        {
            _execute(parameter);
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute(parameter);
        }
    }
}